package service

import (
	"common/biz"
	"common/logs"
	"context"
	"core/dao"
	"core/models/db"
	"core/models/entity"
	"core/models/requests"
	"core/repo"
	"fmt"
	"framework/msError"
	"regexp"
	"sync"
	"time"
	"user/pb"
)

// 创建账号

type AccountService struct {
	sync.RWMutex
	usersErr   map[uint]int64
	accountDao *dao.AccountDao
	configDao  *dao.ConfigDao
	redisDao   *dao.RedisDao
	pb.UnimplementedUserServiceServer
}

func NewAccountService(manager *repo.Manager) *AccountService {
	return &AccountService{
		accountDao: dao.NewAccountDao(manager),
		redisDao:   dao.NewRedisDao(manager),
		configDao:  dao.NewConfigDao(manager),
		usersErr:   make(map[uint]int64),
	}
}

func (a *AccountService) Register(ctx context.Context, req *pb.RegisterParams) (*pb.RegisterResponse, error) {
	//写注册的业务逻辑
	logs.Info("用户手机号:%v，登录方式：%d", req.Account, req.LoginPlatform)
	switch req.LoginPlatform {
	case requests.None:
		ac, count, err := a.phoneLogin(req)
		if err != nil {
			err = &msError.Error{
				Code: err.Code,
				Err:  fmt.Errorf("%v|%d", err.Err.Error(), count),
			}
			return &pb.RegisterResponse{}, msError.GrpcError(err)
		}
		return &pb.RegisterResponse{
			Uid:    fmt.Sprintf("%d", ac.ID),
			Token:  ac.Token,
			RoleID: fmt.Sprintf("%d", ac.RoleID),
		}, nil
	case requests.Account:
		ac, err := a.phoneRegister(req)
		if err != nil {
			return &pb.RegisterResponse{}, msError.GrpcError(err)
		}
		return &pb.RegisterResponse{
			Uid:    fmt.Sprintf("%d", ac.ID),
			Token:  ac.Token,
			RoleID: fmt.Sprintf("%d", ac.RoleID),
		}, nil
	case requests.WeiXin:
		//fmt.Println(req)
		ac, err := a.wxRegister(req)
		if err != nil {
			return &pb.RegisterResponse{}, msError.GrpcError(err)
		}
		return &pb.RegisterResponse{
			Uid:    ac.Uid,
			Token:  "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjAsImV4cCI6MTcwNjUxNDY5M30.cklrY3ssVGcLncirZX046d8Cycigh7-i33fx6Wnaik4",
			RoleID: "1",
		}, nil
	}

	logs.Info("register server called...")
	return &pb.RegisterResponse{}, nil
}

func (a *AccountService) wxRegister(req *pb.RegisterParams) (*entity.Account, *msError.Error) {
	//1. 封装一个account结构体 将其存入数据库 mongo 分布式id objectID
	ac := &entity.Account{
		WxAccount:  req.Account,
		CreateTime: time.Now(),
	}
	//2. 需要生成几个数字作为用户的唯一id redis自增
	uid, err := a.redisDao.NextAccountId()
	if err != nil {
		return ac, biz.SqlError
	}
	ac.Uid = uid
	err = a.accountDao.SaveAccount(context.TODO(), ac)
	if err != nil {
		return ac, biz.SqlError
	}
	return ac, nil
}

// phoneLogin 登录
func (a *AccountService) phoneLogin(req *pb.RegisterParams) (*db.User, int64, *msError.Error) {
	ctx := context.TODO()
	//查看手机号是否注册
	ac := &db.User{
		Username: req.Account,
		Password: req.Password,
	}
	var err *msError.Error
	user := a.accountDao.UserExists(ctx, req.Account)
	if user == nil || user.ID == 0 {
		return nil, 0, biz.AccountNotExist
	}
	info := a.configDao.GetVal(context.TODO(), "is_maintain")
	if info != "0" {
		return nil, 0, biz.Maintain
	}
	if req.Account == "" {
		return nil, 0, biz.AccountOrPasswordError
	}

	if user.Status == 9 {
		return nil, 0, biz.UserClenLoginError
	}
	if user.Status == -1 {
		return nil, 0, biz.BlockedAccount
	}
	a.Lock()
	defer a.Unlock()
	count, _ := a.usersErr[user.ID]
	if count >= 2 {
		get := a.redisDao.RGet(ctx, req.Account)
		if req.SmsCode == "" || get != req.SmsCode {
			count++
			a.usersErr[user.ID] = count
			return nil, count, biz.SmsCodeError
		}
	} else {
		if req.Password == "" {
			return nil, 0, biz.AccountOrPasswordError
		}
	}
	ac, err = a.accountDao.SaveUser(ctx, ac, user.Password, count)
	if err != nil {
		count++
		a.usersErr[user.ID] = count
		return nil, count, err
	}
	ac.ID = user.ID
	ac.RoleID = user.RoleID
	delete(a.usersErr, user.ID)
	return ac, 0, nil
}

// phoneRegister 注册登录
func (a *AccountService) phoneRegister(req *pb.RegisterParams) (*db.User, *msError.Error) {
	ctx := context.TODO()
	//查看手机号是否注册
	if req.Account == "" {
		return nil, biz.AccountOrPasswordEmpty
	}
	if req.Password == "" {
		return nil, biz.AccountOrPasswordEmpty
	}
	if req.SmsCode == "" {
		return nil, biz.SmsCodeError
	}
	regex := regexp.MustCompile("[a-zA-Z]")
	passwordCheck := regex.MatchString(req.Password)
	if !passwordCheck {
		return nil, biz.PasswordError
	}
	regex = regexp.MustCompile("[0-9]")
	passwordCheck = regex.MatchString(req.Password)
	if !passwordCheck {
		return nil, biz.PasswordError
	}
	if len(req.Password) < 6 || len(req.Password) > 12 {
		return nil, biz.PasswordError
	}
	user := a.accountDao.UserExists(ctx, req.Account)
	if user != nil && user.ID != 0 {
		return nil, biz.AccountExist
	}
	ac := &db.User{
		Username:   req.Account,
		Password:   req.Password,
		InviteCode: req.InviteCode,
	}
	var err *msError.Error
	//注册
	get := a.redisDao.RGet(ctx, req.Account)
	if get != req.SmsCode {
		return nil, biz.SmsCodeError
	}
	//a.redisDao.RDel(ctx, req.Account)
	ac, err = a.accountDao.AddUser(ctx, ac)
	if err != nil {
		return ac, err
	}
	return ac, nil
}
